package org.hl7.fhir.r5.test.profiles.codegen;

import java.util.List;
import java.util.ArrayList;
import javax.annotation.Nullable;
import java.util.Date;


import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.profilemodel.PEInstance;
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
import org.hl7.fhir.r5.profilemodel.gen.PEGeneratedBase;
import org.hl7.fhir.r5.profilemodel.gen.Min;
import org.hl7.fhir.r5.profilemodel.gen.Max;
import org.hl7.fhir.r5.profilemodel.gen.Label;
import org.hl7.fhir.r5.profilemodel.gen.Doco;
import org.hl7.fhir.r5.profilemodel.gen.BindingStrength;
import org.hl7.fhir.r5.profilemodel.gen.ValueSet;
import org.hl7.fhir.r5.profilemodel.gen.MustSupport;
import org.hl7.fhir.r5.profilemodel.gen.Definition;


// Generated by the HAPI Java Profile Generator, 5/11/24, 6:00 pm

/**
 * Electronic Product Information Bundle Document. A container for the collection 
 * of resources that make up the ePI document.
 *
 */
public class BundleUvEpi extends PEGeneratedBase {

  public static final String CANONICAL_URL = "http://hl7.org/fhir/uv/emedicinal-product-info/StructureDefinition/Bundle-uv-epi|1.0.0";

  @Min("0") @Max("1") @Doco("")
  private String id;  // 

  @Min("1") @Max("1") @Doco("Persistent identifier for the bundle")
  @Definition("Persistent identifier that remains the same for all versions of this ePI. The identifier remains the same regardless of any changes to the Bundle and regardless of any changes made to the Resources within the Bundle. This purpose of this identifier is to ensure all versions of an ePI can be collected as a set under a common parent identifier.")
  private Identifier identifier;// @NotNull  // Persistent identifier for the bundle

  @Min("1") @Max("1") @Doco("document | message | transaction | transaction-response | batch | batch-response | history | searchset | collection | subscription-notification")
  @BindingStrength("required") @ValueSet("http://hl7.org/fhir/ValueSet/bundle-type|5.0.0")
  @Definition("Indicates the purpose of this bundle - how it is intended to be used.")
  private String type;// @NotNull  // document | message | transaction | transaction-response | batch | batch-response | history | searchset | collection | subscription-notification

  @Min("1") @Max("1") @Doco("Persistent original date of approval")
  @Definition("Original date in which this ePI document received its first authorization. As with the identifier, this date persists across versions. ")
  private Date timestamp;// @NotNull  // Persistent original date of approval

  @Min("0") @Max("1") @Doco("If search, the total number of matches")
  @Definition("If a set of search matches, this is the (potentially estimated) total number of entries of type 'match' across all pages in the search.  It does not include search.mode = 'include' or 'outcome' entries and it does not provide a count of the number of entries in the Bundle.")
  private int total;  // If search, the total number of matches

  @Min("0") @Max("*") @Doco("Links related to this Bundle")
  @Definition("A series of links that provide context to this bundle.")
  private List<BackboneElement> links = new ArrayList<>();  // Links related to this Bundle

  @Min("1") @Max("*") @Doco("Entry resource in the ePI bundle")
  @Definition("An entry resource included in the ePI document bundle resource.")
  private List<BackboneElement> entries = new ArrayList<>();// @NotNull  // Entry resource in the ePI bundle

  @Min("1") @Max("1") @Doco("ePI Composition")
  @Definition("ePI Composition")
  private BackboneElement composition;// @NotNull  // ePI Composition

  @Min("0") @Max("*") @Doco("Organization")
  @Definition("Organization")
  private List<BackboneElement> organizations = new ArrayList<>();  // Organization

  @Min("0") @Max("*") @Doco("Regulated Authorization")
  @Definition("Regulated Authorization")
  private List<BackboneElement> authorizations = new ArrayList<>();  // Regulated Authorization

  @Min("0") @Max("*") @Doco("Medicinal Product")
  @Definition("Medicinal Product Definition")
  private List<BackboneElement> medicinalProducts = new ArrayList<>();  // Medicinal Product

  @Min("0") @Max("*") @Doco("Packaged Product")
  @Definition("Packaged Product Definition")
  private List<BackboneElement> packagedProducts = new ArrayList<>();  // Packaged Product

  @Min("0") @Max("*") @Doco("Administrable Product")
  @Definition("Administrable Product Definition")
  private List<BackboneElement> administrableProducts = new ArrayList<>();  // Administrable Product

  @Min("0") @Max("*") @Doco("Manufactured Item")
  @Definition("Manufactured Item Definition")
  private List<BackboneElement> manufacturedItems = new ArrayList<>();  // Manufactured Item

  @Min("0") @Max("*") @Doco("Ingredient")
  @Definition("Ingredient")
  private List<BackboneElement> ingredients = new ArrayList<>();  // Ingredient

  @Min("0") @Max("*") @Doco("Interactions, Warnings, Indications,Contraindications")
  @Definition("ePI ClinicalUseDefinition used for Interactions, Warnings,Indication, Contraindication")
  private List<BackboneElement> clinicalUses = new ArrayList<>();  // Interactions, Warnings, Indications,Contraindications

  @Min("0") @Max("*") @Doco("Substance Definition")
  @Definition("Substance Definition")
  private List<BackboneElement> substanceDefinitions = new ArrayList<>();  // Substance Definition

  @Min("0") @Max("*") @Doco("Binary")
  @Definition("Binary")
  private List<BackboneElement> binaries = new ArrayList<>();  // Binary

  @Min("0") @Max("1") @Doco("Issues with the Bundle")
  @Definition("Captures issues and warnings that relate to the construction of the Bundle and the content within it.")
  private OperationOutcome issues;  // Issues with the Bundle


  /**
   * Parameter-less constructor.
   *
   */
  public BundleUvEpi() {
    initFixedValues();
  }

  /**
   * Construct an instance of the object, and fill out all the fixed values 
   *
   */
  public BundleUvEpi(IWorkerContext context) {
    initFixedValues();
    workerContext = context;
    PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
    PEInstance src = builder.buildPEInstance(CANONICAL_URL, builder.createResource(CANONICAL_URL, false));
    load(src);
  }

  /**
   * Populate an instance of the object based on this source object 
   *
   */
  public static BundleUvEpi fromSource(IWorkerContext context, Bundle source) {
    BundleUvEpi theThing = new BundleUvEpi();
    theThing.workerContext = context;
    PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
    PEInstance src = builder.buildPEInstance(CANONICAL_URL, source);
    theThing.load(src);
    return theThing;
  }


  public void load(PEInstance src) {
    clear();
    if (src.hasChild("id")) {
      id = ((IdType) src.child("id").asDataType()).getValue();
    }
    if (src.hasChild("identifier")) {
      identifier = (Identifier) src.child("identifier").asDataType();
    }
    if (src.hasChild("type")) {
      type = src.child("type").asDataType().primitiveValue();
    }
    if (src.hasChild("timestamp")) {
      timestamp = ((InstantType) src.child("timestamp").asDataType()).getValue();
    }
    if (src.hasChild("total")) {
      total = ((UnsignedIntType) src.child("total").asDataType()).getValue();
    }
    for (PEInstance item : src.children("link")) {
      links.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("entry")) {
      entries.add((BackboneElement) item.asElement());
    }
    if (src.hasChild("composition")) {
      composition = (BackboneElement) src.child("composition").asElement();
    }
    for (PEInstance item : src.children("organization")) {
      organizations.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("authorization")) {
      authorizations.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("medicinalProduct")) {
      medicinalProducts.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("packagedProduct")) {
      packagedProducts.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("administrableProduct")) {
      administrableProducts.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("manufacturedItem")) {
      manufacturedItems.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("ingredient")) {
      ingredients.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("clinicalUse")) {
      clinicalUses.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("substanceDefinition")) {
      substanceDefinitions.add((BackboneElement) item.asElement());
    }
    for (PEInstance item : src.children("binary")) {
      binaries.add((BackboneElement) item.asElement());
    }
    if (src.hasChild("issues")) {
      issues = (OperationOutcome) src.child("issues").asResource();
    }

  }

  /**
   * Build a instance of the underlying object based on this wrapping object 
   *
   */
  public Bundle build(IWorkerContext context) {
    workerContext = context;
    return build();
  }

  /**
   * Build a instance of the underlying object based on this wrapping object 
   *
   */
  public Bundle build() {
    Bundle theThing = new Bundle();
    PEBuilder builder = new PEBuilder(workerContext, PEElementPropertiesPolicy.EXTENSION, true);
    PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, theThing);
    save(tgt, false);
    return theThing;
  }

  /**
   * Save this profile class into an existing resource (overwriting anything that 
   * exists in the profile) 
   *
   */
  public void save(IWorkerContext context, Bundle dest, boolean nulls) {
    workerContext = context;
    PEBuilder builder = new PEBuilder(context, PEElementPropertiesPolicy.EXTENSION, true);
    PEInstance tgt = builder.buildPEInstance(CANONICAL_URL, dest);
    save(tgt, nulls);
  }

  public void save(PEInstance tgt, boolean nulls) {
    tgt.clear("id");
    if (id != null) {
      tgt.makeChild("id").data().setProperty("value", new IdType(id));
    }
    tgt.clear("identifier");
    if (identifier != null) {
      tgt.addChild("identifier", identifier);
    }
    tgt.clear("type");
    if (type != null) {
      tgt.makeChild("type").data().setProperty("value", new CodeType(type));
    }
    tgt.clear("timestamp");
    if (timestamp != null) {
      tgt.addChild("timestamp", new InstantType(timestamp));
    }
    tgt.clear("total");
    if (total != 0) {
      tgt.makeChild("total").data().setProperty("value", new UnsignedIntType(total));
    }
    tgt.clear("link");
    for (BackboneElement item : links) {
      tgt.addChild("link", item);
    }
    tgt.clear("entry");
    for (BackboneElement item : entries) {
      tgt.addChild("entry", item);
    }
    tgt.clear("composition");
    if (composition != null) {
      tgt.addChild("composition", composition);
    }
    tgt.clear("organization");
    for (BackboneElement item : organizations) {
      tgt.addChild("organization", item);
    }
    tgt.clear("authorization");
    for (BackboneElement item : authorizations) {
      tgt.addChild("authorization", item);
    }
    tgt.clear("medicinalProduct");
    for (BackboneElement item : medicinalProducts) {
      tgt.addChild("medicinalProduct", item);
    }
    tgt.clear("packagedProduct");
    for (BackboneElement item : packagedProducts) {
      tgt.addChild("packagedProduct", item);
    }
    tgt.clear("administrableProduct");
    for (BackboneElement item : administrableProducts) {
      tgt.addChild("administrableProduct", item);
    }
    tgt.clear("manufacturedItem");
    for (BackboneElement item : manufacturedItems) {
      tgt.addChild("manufacturedItem", item);
    }
    tgt.clear("ingredient");
    for (BackboneElement item : ingredients) {
      tgt.addChild("ingredient", item);
    }
    tgt.clear("clinicalUse");
    for (BackboneElement item : clinicalUses) {
      tgt.addChild("clinicalUse", item);
    }
    tgt.clear("substanceDefinition");
    for (BackboneElement item : substanceDefinitions) {
      tgt.addChild("substanceDefinition", item);
    }
    tgt.clear("binary");
    for (BackboneElement item : binaries) {
      tgt.addChild("binary", item);
    }
    tgt.clear("issues");
    if (issues != null) {
      tgt.addChild("issues", issues);
    }

  }

  private void initFixedValues() {
    type = "document";

  }

  public String getId() {
    return id;
  }

  public BundleUvEpi setId(String value) {
    this.id = value;
    return this;
  }

  public boolean hasId() {
    return id != null;
  }

  /**
   * Persistent identifier that remains the same for all versions of this ePI. The 
   * identifier remains the same regardless of any changes to the Bundle and 
   * regardless of any changes made to the Resources within the Bundle. This purpose 
   * of this identifier is to ensure all versions of an ePI can be collected as a set 
   * under a common parent identifier.
   *
   */
  public Identifier getIdentifier() {
    if (identifier == null) { identifier = new Identifier(); }
    return identifier;
  }

  public BundleUvEpi setIdentifier(Identifier value) {
    this.identifier = value;
    return this;
  }
  public boolean hasIdentifier() {
    return identifier != null;
  }

  /**
   * Indicates the purpose of this bundle - how it is intended to be used.
   *
   */
  public String getType() {
    return type;
  }

  public boolean hasType() {
    return true;
  }

  /**
   * Original date in which this ePI document received its first authorization. As 
   * with the identifier, this date persists across versions. 
   *
   */
  public Date getTimestamp() {
    return timestamp;
  }

  public BundleUvEpi setTimestamp(Date value) {
    this.timestamp = value;
    return this;
  }

  public boolean hasTimestamp() {
    return timestamp != null;
  }

  /**
   * If a set of search matches, this is the (potentially estimated) total number of 
   * entries of type 'match' across all pages in the search.  It does not include 
   * search.mode = 'include' or 'outcome' entries and it does not provide a count of 
   * the number of entries in the Bundle.
   *
   */
  public int getTotal() {
    return total;
  }

  public BundleUvEpi setTotal(int value) {
    this.total = value;
    return this;
  }

  public boolean hasTotal() {
    return total != 0;
  }

  /**
   * A series of links that provide context to this bundle.
   *
   */
  public List<BackboneElement> getLinks() {
    if (links == null) { links = new ArrayList<>(); }
    return links;
  }

  public boolean hasLinks() {
    return links != null && !links.isEmpty();
  }

  public boolean hasLink(BackboneElement item) {
    return hasLinks() && links.contains(item);
  }

  public void removeLink(BackboneElement item) {
    if (hasLink(item)) {
      links.remove(item);
    }
  }


  /**
   * An entry resource included in the ePI document bundle resource.
   *
   */
  public List<BackboneElement> getEntries() {
    if (entries == null) { entries = new ArrayList<>(); }
    return entries;
  }

  public boolean hasEntries() {
    return entries != null && !entries.isEmpty();
  }

  public boolean hasEntry(BackboneElement item) {
    return hasEntries() && entries.contains(item);
  }

  public void removeEntry(BackboneElement item) {
    if (hasEntry(item)) {
      entries.remove(item);
    }
  }


  /**
   * ePI Composition
   *
   */
  public @Nullable BackboneElement getComposition() { // BackboneElement is abstract 
    return composition;
  }

  public BundleUvEpi setComposition(BackboneElement value) {
    this.composition = value;
    return this;
  }
  public boolean hasComposition() {
    return composition != null;
  }

  /**
   * Organization
   *
   */
  public List<BackboneElement> getOrganizations() {
    if (organizations == null) { organizations = new ArrayList<>(); }
    return organizations;
  }

  public boolean hasOrganizations() {
    return organizations != null && !organizations.isEmpty();
  }

  public boolean hasOrganization(BackboneElement item) {
    return hasOrganizations() && organizations.contains(item);
  }

  public void removeOrganization(BackboneElement item) {
    if (hasOrganization(item)) {
      organizations.remove(item);
    }
  }


  /**
   * Regulated Authorization
   *
   */
  public List<BackboneElement> getAuthorizations() {
    if (authorizations == null) { authorizations = new ArrayList<>(); }
    return authorizations;
  }

  public boolean hasAuthorizations() {
    return authorizations != null && !authorizations.isEmpty();
  }

  public boolean hasAuthorization(BackboneElement item) {
    return hasAuthorizations() && authorizations.contains(item);
  }

  public void removeAuthorization(BackboneElement item) {
    if (hasAuthorization(item)) {
      authorizations.remove(item);
    }
  }


  /**
   * Medicinal Product Definition
   *
   */
  public List<BackboneElement> getMedicinalProducts() {
    if (medicinalProducts == null) { medicinalProducts = new ArrayList<>(); }
    return medicinalProducts;
  }

  public boolean hasMedicinalProducts() {
    return medicinalProducts != null && !medicinalProducts.isEmpty();
  }

  public boolean hasMedicinalProduct(BackboneElement item) {
    return hasMedicinalProducts() && medicinalProducts.contains(item);
  }

  public void removeMedicinalProduct(BackboneElement item) {
    if (hasMedicinalProduct(item)) {
      medicinalProducts.remove(item);
    }
  }


  /**
   * Packaged Product Definition
   *
   */
  public List<BackboneElement> getPackagedProducts() {
    if (packagedProducts == null) { packagedProducts = new ArrayList<>(); }
    return packagedProducts;
  }

  public boolean hasPackagedProducts() {
    return packagedProducts != null && !packagedProducts.isEmpty();
  }

  public boolean hasPackagedProduct(BackboneElement item) {
    return hasPackagedProducts() && packagedProducts.contains(item);
  }

  public void removePackagedProduct(BackboneElement item) {
    if (hasPackagedProduct(item)) {
      packagedProducts.remove(item);
    }
  }


  /**
   * Administrable Product Definition
   *
   */
  public List<BackboneElement> getAdministrableProducts() {
    if (administrableProducts == null) { administrableProducts = new ArrayList<>(); }
    return administrableProducts;
  }

  public boolean hasAdministrableProducts() {
    return administrableProducts != null && !administrableProducts.isEmpty();
  }

  public boolean hasAdministrableProduct(BackboneElement item) {
    return hasAdministrableProducts() && administrableProducts.contains(item);
  }

  public void removeAdministrableProduct(BackboneElement item) {
    if (hasAdministrableProduct(item)) {
      administrableProducts.remove(item);
    }
  }


  /**
   * Manufactured Item Definition
   *
   */
  public List<BackboneElement> getManufacturedItems() {
    if (manufacturedItems == null) { manufacturedItems = new ArrayList<>(); }
    return manufacturedItems;
  }

  public boolean hasManufacturedItems() {
    return manufacturedItems != null && !manufacturedItems.isEmpty();
  }

  public boolean hasManufacturedItem(BackboneElement item) {
    return hasManufacturedItems() && manufacturedItems.contains(item);
  }

  public void removeManufacturedItem(BackboneElement item) {
    if (hasManufacturedItem(item)) {
      manufacturedItems.remove(item);
    }
  }


  /**
   * Ingredient
   *
   */
  public List<BackboneElement> getIngredients() {
    if (ingredients == null) { ingredients = new ArrayList<>(); }
    return ingredients;
  }

  public boolean hasIngredients() {
    return ingredients != null && !ingredients.isEmpty();
  }

  public boolean hasIngredient(BackboneElement item) {
    return hasIngredients() && ingredients.contains(item);
  }

  public void removeIngredient(BackboneElement item) {
    if (hasIngredient(item)) {
      ingredients.remove(item);
    }
  }


  /**
   * ePI ClinicalUseDefinition used for Interactions, Warnings,Indication, 
   * Contraindication
   *
   */
  public List<BackboneElement> getClinicalUses() {
    if (clinicalUses == null) { clinicalUses = new ArrayList<>(); }
    return clinicalUses;
  }

  public boolean hasClinicalUses() {
    return clinicalUses != null && !clinicalUses.isEmpty();
  }

  public boolean hasClinicalUse(BackboneElement item) {
    return hasClinicalUses() && clinicalUses.contains(item);
  }

  public void removeClinicalUse(BackboneElement item) {
    if (hasClinicalUse(item)) {
      clinicalUses.remove(item);
    }
  }


  /**
   * Substance Definition
   *
   */
  public List<BackboneElement> getSubstanceDefinitions() {
    if (substanceDefinitions == null) { substanceDefinitions = new ArrayList<>(); }
    return substanceDefinitions;
  }

  public boolean hasSubstanceDefinitions() {
    return substanceDefinitions != null && !substanceDefinitions.isEmpty();
  }

  public boolean hasSubstanceDefinition(BackboneElement item) {
    return hasSubstanceDefinitions() && substanceDefinitions.contains(item);
  }

  public void removeSubstanceDefinition(BackboneElement item) {
    if (hasSubstanceDefinition(item)) {
      substanceDefinitions.remove(item);
    }
  }


  /**
   * Binary
   *
   */
  public List<BackboneElement> getBinaries() {
    if (binaries == null) { binaries = new ArrayList<>(); }
    return binaries;
  }

  public boolean hasBinaries() {
    return binaries != null && !binaries.isEmpty();
  }

  public boolean hasBinary(BackboneElement item) {
    return hasBinaries() && binaries.contains(item);
  }

  public void removeBinary(BackboneElement item) {
    if (hasBinary(item)) {
      binaries.remove(item);
    }
  }


  /**
   * Captures issues and warnings that relate to the construction of the Bundle and 
   * the content within it.
   *
   */
  public OperationOutcome getIssues() {
    if (issues == null) { issues = new OperationOutcome(); }
    return issues;
  }

  public BundleUvEpi setIssues(OperationOutcome value) {
    this.issues = value;
    return this;
  }
  public boolean hasIssues() {
    return issues != null;
  }



  public void clear() {
    id = null;
    identifier = null;
    type = null;
    timestamp = null;
    total = 0;
    links.clear();
    entries.clear();
    composition = null;
    organizations.clear();
    authorizations.clear();
    medicinalProducts.clear();
    packagedProducts.clear();
    administrableProducts.clear();
    manufacturedItems.clear();
    ingredients.clear();
    clinicalUses.clear();
    substanceDefinitions.clear();
    binaries.clear();
    issues = null;

  }

}
